#ifndef  __TSA_FSM_H__
#define  __TSA_FSM_H__

typedef void(*STATE_OPERATION)(void * this);

/// each state has 3 operations:
/// - enter() is executed when enter this state from other states
/// - run() is executed cyclically when in this state
/// - exit() is executed when exit from this state to other states
typedef struct 
{
    STATE_OPERATION enter;
    STATE_OPERATION run;
    STATE_OPERATION exit;
}
FSM_OPERATION;

/// each transition (on event) has 2 elements:
/// - nextState which state will be transit to, if -1, keep the current state
/// - transit() operation will be executed when transit to the next state
#define  FSM_KEEP  -1
typedef struct
{
    int nextState;
    STATE_OPERATION transit;
}
FSM_TRANSITION_ON_EVENT;

/// each transition (from state) has an array of transitions (on event)
typedef struct
{
	const FSM_TRANSITION_ON_EVENT * onEvent;
}
FSM_TRANSITION_FROM_STATE;

/// each state machine has a descriptor telling:
/// - default state (init state)
/// - total numbers of states
/// - total numbers of events
/// - pointer to the operations of states
/// - pointer to the transitions of states
typedef struct
{
    int defaultState;
    int totalNumberOfStates;
    int totalNumberOfEvents;
    const FSM_OPERATION * operationsOfState;
    const FSM_TRANSITION_FROM_STATE * transitionFromState;
}
FSM_DESCRIPTOR;

/// a FSM has 3 parts:
/// - descriptor
/// - user
/// - state
typedef struct
{
    /// descriptor
    const FSM_DESCRIPTOR * pDescriptor;

    /// user info to identify the FSM by the user
    int user;

    /// runtime
    int state, fromState, toState, event;
}
FSM_DATA;

extern void fsm_init(FSM_DATA * this, const FSM_DESCRIPTOR * pDescriptor, int user);

extern void fsm_run(FSM_DATA * this);

extern void fsm_transit(FSM_DATA * this, int event);

#endif /// __TSA_FSM_H__

